package com.edianping.algorithm;

import java.util.List;

import org.apache.log4j.Logger;

import com.edianping.bean.ReviewItemBean;
import com.edianping.bean.ShopItemBean;
import com.edianping.config.ConstVars;
import com.edianping.store.ReviewDBStore;
import com.edianping.store.ShopDBStore;

public class AlgorithmShopNew implements IAlgorithm {
	private static Logger log = Logger.getLogger(AlgorithmShopNew.class);
	
	@Override
	public int calculateScore( List<ReviewItemBean> list ){
		return (int)doCalculate(list, ConstVars.SCORE);
	}
	
	@Override
	public int calculateRate( List<ReviewItemBean> list ){
		return (int)doCalculate(list, ConstVars.RATE);
	}
	
	@Override
	public int calculateVelocity( List<ReviewItemBean> list ){
		return (int)doCalculate(list, ConstVars.VELOCITY);
	}
	
	@Override
	public int calculateService( List<ReviewItemBean> list ){
		return (int)doCalculate(list, ConstVars.SERVICE);
	}
	
	@Override
	public int calculateReality( List<ReviewItemBean> list ){
		return (int)doCalculate(list, ConstVars.REALITY);
	}
	
	/**
	 * use the given formula to calculate the score
	 * 
	 * @param list
	 * @return
	 */
	private double doCalculate( List<ReviewItemBean> list, int type ){
		double result = 0;
		
		double sum1 = 0;
		double sum2 = 0;
		
		for( ReviewItemBean item : list ){
			// (Comment Quality + User Rep) / item weight
			//involve the time as weight here
			double T = item.getWeight()+1;
			double base = Math.log( T )/Math.log( 2 );
			double W = ( getCommentQulity( item ) + getUserReputation( item.getUserid(), item.getLoginCount() ) )/base;
			
			double score = 0;
			
			switch( type ){
			case ConstVars.SCORE:
				score = item.getScore();
				break;
			case ConstVars.RATE:
				score = item.getRate();
				break;
			case ConstVars.SERVICE:
				score = item.getService();
				break;
			case ConstVars.REALITY:
				score = item.getReality();
				break;
			case ConstVars.VELOCITY:
				score = item.getVelocity();
				break;
			}
			
			sum1 += W*score;
			sum2 += W;
		}
		
		if( sum2 != 0 ){
			result = sum1*10/sum2;
			log.debug("sum2 is "+sum2+", the score is:"+result);
		}
		else{
			log.debug("sum2 is zero, so the score has to be zero");
		}
	
		if( result < 0 )
		{
			log.info( "result is less than 0" );
			result = 0;
		}
	
		return result;
	}
	
	private double getUserReputation( int userId, int loginCount ){
		List<ReviewItemBean> allHisReview = ReviewDBStore.GetReviewByUid( userId );
		double result = 0;
		if( allHisReview.size() >= 3 ){
			double qulity=0;
			for( ReviewItemBean item : allHisReview){
				qulity += getCommentQulity( item );
			}
			result = qulity * getAlpha( loginCount, 30)/ allHisReview.size();
		}
		else{
			result = getAlpha( loginCount, 30 ) * 50;
		}
		
		return result;
	}
	
	/**
	 * get the alpha parameter
	 * 
	 * @param loginCount
	 * @param T default T is 30
	 * @return
	 */
	private double getAlpha( int loginCount, int T ){
		double result = Math.log( loginCount+1 )/Math.log( T );
		return result;
	}
	
	/**
	 * Get comment qulity
	 * @param item
	 * @return
	 */
	private double getCommentQulity( ReviewItemBean item ){
		double result = 0;
		
//		字数>250，且有大于3张图片 100分
//		字数>250，且有1至2张图片 90分
//		字数>250
//		80分
//		字数在200-250
//		70分
//		字数在150-199
//		60分
//		字数在100-149
//		50分
//		字数在75-99
//		40分
//		字数在50-74
//		30分
//		字数在25-49
//		20分
//		字数小于25
//		10分
		
		if( item.getCommentLength() >=250 ){
			if(item.getPicCount() > 3 )
				result = 100;
			else if( item.getPicCount() > 1 )
				result = 90;
			else
				result = 80;
		}
		else if( item.getCommentLength() >=200 )
			result = 70;
		else if( item.getCommentLength() >=150 )
			result = 60;
		else if( item.getCommentLength() >=100 )
			result = 50;
		else if( item.getCommentLength() >=75 )
			result = 40;
		else if( item.getCommentLength() >=50 )
			result = 30;
		else if( item.getCommentLength() >=25 )
			result = 20;
		else
			result = 10;
		
		return result;
	}
	
	public static void main(String[] args) {
		AlgorithmShopNew algorithnShop = new AlgorithmShopNew();
		System.out.println( algorithnShop.calculateScore( ReviewDBStore.GetReviewsByShopId(203995) ) );
		System.out.println( algorithnShop.calculateRate( ReviewDBStore.GetReviewsByShopId(203995) ) );
		System.out.println( algorithnShop.calculateReality( ReviewDBStore.GetReviewsByShopId(203995) ) );
		System.out.println( algorithnShop.calculateService( ReviewDBStore.GetReviewsByShopId(203995) ) );
		System.out.println( algorithnShop.calculateVelocity( ReviewDBStore.GetReviewsByShopId(203995) ) );
	}
}
